Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for the default MemCacheStore from ActiveSupport #465

Merged
merged 1 commit into from
Jun 30, 2020

Conversation

casperisfine
Copy link
Contributor

Long story short, memcached is getting increasingly problematic, it's not really well maintained, and anyway it's based on the deprecated libmemcached.

Most newer app uses dalli through Rails built-in MemCacheStore backend, so supporting it is very appealing. You might know that the binary protocol dalli uses is about to be deprecated as well in favor of the new "meta commands" protocol, but I'm fairly confident the Dalli can be converted to that new protocol just fine.

So I tried it, and it was surprisingly easy. The only downside was that I had to extend MemCacheStore, but that was to be expected.

Also if this PR is merged, the README could be updated to advise on using Dalli, but I'd need to check on the configuration options.

Copy link
Contributor

@dylanahsmith dylanahsmith left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also if this PR is merged, the README could be updated to advise on using Dalli, but I'd need to check on the configuration options.

👍. I think we mainly just need to recommend using failover: false which sounds like the same thing as auto_eject_hosts: false that we currently recommend for MemcachedStore.

@@ -12,6 +12,10 @@ def initialize(cache_adaptor = nil)
end

def cache_backend=(cache_adaptor)
if cache_adaptor.class.name == 'ActiveSupport::Cache::MemCacheStore'
cache_adaptor.extend(MemCacheStoreCAS)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we wrap the cache adapter rather than mutating it with extend? Since ideally we would add CAS support to ActiveSupport::Cache::MemCacheStore itself, in which case we could have a conflict from this extension affecting code using the adapter independently of this library.

It means we would need to get the underlying dalli client using cache_store.instance_variable_get(:@data), but the coupling would be the same.

@rafaelfranca should ActiveSupport::Cache::MemCacheStore expose the underlying dalli client? That would be consistent with the database adapters which expose the underlying client through raw_connection.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we wrap the cache adapter rather than mutating it with extend?

I thought about that, but we need to access a bunch of private methods like merged_options, etc. So it makes the code much more terse.

Since ideally we would add CAS support to ActiveSupport::Cache::MemCacheStore itself

ActiveSupport::Cache has no CAS support, but maybe it should, it could be worth starting a discussion upstream, since other backends such as Redis could support it. However I'm not sure the interface would be the same anyway.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure the interface would be the same anyway.

Yeah, the fact that the interface might not be the same is why I'm thinking it being implemented upstream could cause a conflict.

I thought about that, but we need to access a bunch of private methods like merged_options, etc. So it makes the code much more terse.

Good point. Maybe this is a good use case for a refinement.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this is a good use case for a refinement.

Oh, good idea, I never think of that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, not sure if a refinement would be very practical, as we'd have to conditionally activate it. But we only know if it's useful much later at runtime. And nothing guarantees than checking for defined? AS::Cache::MemCacheStore at load time would be accurate.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, refinements are statically scoped, which doesn't work as well for extending an optional dependency. Maybe we should just raise if the AS::Cache::MemCacheStore object responds to cas or cas_multi, then handle that compatibility in this library if/when CAS support is added upstream.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's probably the best idea.

Anyway if cas make it to AS::Cache, it's likely one of us who'll PR it so I think we'll know :)

@casperisfine casperisfine force-pushed the dalli-support branch 2 times, most recently from ee09ad9 to 1b3dcf6 Compare June 30, 2020 18:53
@casperisfine casperisfine merged commit c729922 into master Jun 30, 2020
@casperisfine casperisfine deleted the dalli-support branch June 30, 2020 21:05
@casperisfine
Copy link
Contributor Author

Not really related with IDC itself, but another thing that is lost when using the Dalli based MemCacheStore, is that you can no longer pass a custom coder:. Or more accurately you can pass it to the Dalli client, but then it will receive a CacheEntry instance, and you need to turn off AS::Cache compression. That's quite finicky.

I'm trying to see if I can refactor AS::Cache to make that a bit more usable, but it's hard without breaking backward compat.

@shopify-shipit shopify-shipit bot temporarily deployed to rubygems June 30, 2020 21:23 Inactive
@saiqulhaq saiqulhaq mentioned this pull request Jul 2, 2020
@mmalek-sa
Copy link

Any plans to release a new version with this integration? We need the integration but don't want to use master on our Gemfile.

@casperisfine
Copy link
Contributor Author

It's true that we didn't have a release in quite a long time. But I'm not too sure how stable master is. @dylanahsmith what do you think?

@dylanahsmith
Copy link
Contributor

I think master is fairly stable at the moment and we should probably make a release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants